package com.asen.commons.core.base.controller.inner;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.asen.commons.core.base.domain.Core;
import com.asen.commons.core.base.dto.CommonInnerDto;
import com.asen.commons.core.base.service.CoreService;
import com.asen.commons.core.meta.dao.Condition;
import com.asen.commons.exception.FeignServerException;
import com.asen.commons.exception.IllegalLogicException;
import com.asen.commons.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 通用接口
 *
 * @author Gary
 * @version 1.0
 * @date 2019-02-27
 */
@Slf4j
@RestController
@RequestMapping("/inner/common")
public class CommonInnerController {

    @RequestMapping(value = "/get")
    public <T extends Core> T get(@RequestParam("modelClass") String modelClass, @RequestParam("id") Long id) {
        try {
            CoreService<T> service = getServiceBean(modelClass, "get");
            T t = service.get(id);
            return t;
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    return service.get(id);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【get】方法！单据类型：" + modelClass);
            //    // Method rejectMethod = serviceBean.getClass().getMethod("get", Long.class);
            //    // return rejectMethod.invoke(serviceBean, id);
            //}
        } catch (Exception e) {
            // if (e instanceof NoSuchMethodException) {
            //     log.error("服务不支持get方法，单据类型：" + modelClass, e);
            //     throw new IllegalLogicException("服务不支持默认【get】方法！单据类型：" + modelClass);
            // }
            log.error("获取详情异常：modelName=" + modelClass + ", id=" + id, e);
            throw new FeignServerException(e);
        }
    }

    @RequestMapping(value = "/getBy")
    public <T extends Core> T getBy(@RequestParam("modelClass") String modelClass, @RequestBody Condition condition) {
        try {
            CoreService<T> service = getServiceBean(modelClass, "getBy");
            return service.getBy(condition);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    return service.getBy(condition);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【getBy】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("查询详情异常：modelClass=" + modelClass + ", condition=" + condition, e);
            throw new FeignServerException(e);
        }
    }

    @RequestMapping(value = "/list")
    public <T extends Core> List<T> list(@RequestParam("modelClass") String modelClass, @RequestBody Condition condition) {
        List<T> list = null;
        try {
            CoreService<T> service = getServiceBean(modelClass, "list");
            list = service.getList(condition);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    list = service.getList(condition);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【list】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("查询列表异常：modelClass=" + modelClass + ", condition=" + condition, e);
            throw new FeignServerException(e.getMessage());
        }
        return list;
    }

    /**
     * 获取list-组织隔离
     */
    @RequestMapping(value = "/listIsolation")
    public <T extends Core> List<T> listIsolation(@RequestParam("modelClass") String modelClass, @RequestBody Condition condition) {
        List<T> list = null;
        try {
            CoreService<T> service = getServiceBean(modelClass, "listIsolation");
            list = service.getListIsolation(condition);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    list = service.getListIsolation(condition);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【listIsolation】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("查询列表-数据隔离异常：modelClass=" + modelClass + ", condition=" + condition, e);
            throw new FeignServerException(e.getMessage());
        }
        return list;
    }

    @RequestMapping(value = "/count")
    public <T extends Core> Integer count(@RequestParam("modelClass") String modelClass, @RequestBody Condition condition) {
        Integer count = null;
        try {
            CoreService<T> service = getServiceBean(modelClass, "count");
            count = service.count(condition);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    count = service.count(condition);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【count】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("查询列表异常：modelClass=" + modelClass + ", condition=" + condition, e);
            throw new FeignServerException(e.getMessage());
        }
        return count;
    }

    @RequestMapping(value = "/countIsolation")
    public <T extends Core> Integer countIsolation(@RequestParam("modelClass") String modelClass, @RequestBody Condition condition) {
        Integer count = null;
        try {
            CoreService<T> service = getServiceBean(modelClass, "countIsolation");
            count = service.countIsolation(condition);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    count = service.countIsolation(condition);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【count】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("查询列表异常：modelClass=" + modelClass + ", condition=" + condition, e);
            throw new FeignServerException(e.getMessage());
        }
        return count;
    }

    @RequestMapping(value = "/add")
    public <T extends Core> Long add(@RequestParam("modelClass") String modelClass, @RequestBody JSONObject jsonObject) {
        BaseAssert.notEmpty(modelClass, "参数modelClas不能为空！");
        BaseAssert.notNull(jsonObject, "参数jsonObject不能为空！");

        Long id = null;

        try {
            CoreService<T> service = getServiceBean(modelClass, "add");
            Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            T model = jsonObject.toJavaObject(modelClazz);
            service.add(model);
            id = model.getId();
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            //    T model = jsonObject.toJavaObject(modelClazz);
            //    service.add(model);
            //    id = model.getId();
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【add】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("新增失败", e);
            throw new FeignServerException(e.getMessage());
        }

        return id;
    }

    @RequestMapping(value = "/batchAdd")
    public <T extends Core> List<Long> batchAdd(@RequestParam("modelClass") String modelClass, @RequestBody JSONArray jsonArray) {
        BaseAssert.notEmpty(modelClass, "参数modelClas不能为空！");
        BaseAssert.notEmpty(jsonArray, "参数jsonArray不能为空！");

        List<Long> ids = null;

        try {
            CoreService<T> service = getServiceBean(modelClass, "batchAdd");
            Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            List<T> list = jsonArray.toJavaList(modelClazz);
            service.batchAdd(list);
            ids = list.stream().map(T::getId).collect(Collectors.toList());
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            //    List<T> list = jsonArray.toJavaList(modelClazz);
            //    service.batchAdd(list);
            //    ids = list.stream().map(T::getId).collect(Collectors.toList());
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【batchAdd】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("新增失败", e);
            throw new FeignServerException(e.getMessage());
        }

        return ids;
    }

    @RequestMapping(value = "/update")
    public <T extends Core> void update(@RequestParam("modelClass") String modelClass, @RequestBody JSONObject jsonObject) {
        try {
            CoreService<T> service = getServiceBean(modelClass, "update");
            Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            T model = jsonObject.toJavaObject(modelClazz);
            service.update(model);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            //    T model = jsonObject.toJavaObject(modelClazz);
            //    service.update(model);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【update】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("修改失败", e);
            throw new FeignServerException(e.getMessage());
        }
    }

    @RequestMapping(value = "/batchUpdate")
    public <T extends Core> List<Long> batchUpdate(@RequestParam("modelClass") String modelClass, @RequestBody JSONArray jsonArray) {
        BaseAssert.notEmpty(modelClass, "参数modelClas不能为空！");
        BaseAssert.notEmpty(jsonArray, "参数jsonArray不能为空！");

        List<Long> ids = null;

        try {
            CoreService<T> service = getServiceBean(modelClass, "batchUpdate");
            Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            List<T> list = jsonArray.toJavaList(modelClazz);
            service.batchUpdate(list);
            ids = list.stream().map(T::getId).collect(Collectors.toList());
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            //    List<T> list = jsonArray.toJavaList(modelClazz);
            //    service.batchUpdate(list);
            //    ids = list.stream().map(T::getId).collect(Collectors.toList());
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【batchUpdate】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("新增失败", e);
            throw new FeignServerException(e.getMessage());
        }

        return ids;
    }

    @RequestMapping(value = "/updatePartial")
    public <T extends Core> void updatePartial(@RequestParam("modelClass") String modelClass, @RequestBody CommonInnerDto dto) {
        try {
            CoreService<T> service = getServiceBean(modelClass, "updatePartial");
            Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            String json = JSON.toJSONString(dto.getModel());
            T model = JSON.parseObject(json, modelClazz);
            service.updatePartial(model, dto.getPartialFields());
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            //    String json = JSON.toJSONString(dto.getModel());
            //    T model = JSON.parseObject(json, modelClazz);
            //    service.updatePartial(model, dto.getPartialFields());
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【updatePartial】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("修改失败", e);
            throw new FeignServerException(e.getMessage());
        }
    }

    @RequestMapping(value = "/batchUpdatePartial")
    public <T extends Core> void batchUpdatePartial(@RequestParam("modelClass") String modelClass, @RequestBody CommonInnerDto dto) {
        try {
            if (CollectionUtils.isEmpty(dto.getModels())) {
                return;
            }
            CoreService<T> service = getServiceBean(modelClass, "batchUpdatePartial");
            Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            List<T> list = new ArrayList<>();
            Collection models = dto.getModels();
            for (Object object : models) {
                String json = JSON.toJSONString(object);
                T model = JSON.parseObject(json, modelClazz);
                list.add(model);
            }
            service.batchUpdatePartial(list, dto.getPartialFields());
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            //    List<T> list = new ArrayList<>();
            //    Collection models = dto.getModels();
            //    for (Object object : models) {
            //        String json = JSON.toJSONString(object);
            //        T model = JSON.parseObject(json, modelClazz);
            //        list.add(model);
            //    }
            //    service.batchUpdatePartial(list, dto.getPartialFields());
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【batchUpdatePartial】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("修改失败", e);
            throw new FeignServerException(e.getMessage());
        }
    }

    @RequestMapping(value = "/batchRemove")
    public <T extends Core> void batchRemove(@RequestParam("modelClass") String modelClass, @RequestBody JSONArray jsonArray) {
        BaseAssert.notEmpty(modelClass, "参数modelClas不能为空！");
        BaseAssert.notEmpty(jsonArray, "参数jsonArray不能为空！");

        try {
            CoreService<T> service = getServiceBean(modelClass, "batchRemove");
            Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            List<T> list = jsonArray.toJavaList(modelClazz);
            service.batchRemove(list);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            //    List<T> list = jsonArray.toJavaList(modelClazz);
            //    service.batchRemove(list);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【batchRemove】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("批量删除失败", e);
            throw new FeignServerException(e.getMessage());
        }
    }

    @RequestMapping(value = "/remove")
    public <T extends Core> void remove(@RequestParam("modelClass") String modelClass, @RequestParam("id") Long id) {
        try {
            CoreService<T> service = getServiceBean(modelClass, "remove");
            Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            T model = modelClazz.newInstance();
            model.setId(id);
            service.remove(model);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    Class<T> modelClazz = (Class<T>) ClassUtils.forName(modelClass);
            //    T model = modelClazz.newInstance();
            //    model.setId(id);
            //    service.remove(model);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【remove】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("删除失败", e);
            throw new FeignServerException(e.getMessage());
        }
    }

    @RequestMapping(value = "/removeBy")
    public <T extends Core> void removeBy(@RequestParam("modelClass") String modelClass,
                                          @RequestParam(value = "updateTime", required = false) Boolean updateTime,
                                          @RequestBody Condition condition) {
        try {
            CoreService<T> service = getServiceBean(modelClass, "removeBy");
            service.removeBy(condition, updateTime == null ? false : updateTime);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    service.removeBy(condition, updateTime == null ? false : updateTime);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【removeBy】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("删除失败", e);
            throw new FeignServerException(e.getMessage());
        }
    }

    @RequestMapping(value = "/removeByCompletely")
    public <T extends Core> void removeByCompletely(@RequestParam("modelClass") String modelClass,
                                          @RequestParam(value = "updateTime", required = false) Boolean updateTime,
                                          @RequestBody Condition condition) {
        try {
            CoreService<T> service = getServiceBean(modelClass, "removeByCompletely");
            service.removeByCompletely(condition);
            //Object serviceBean = BillTypeUtils.getServiceBean(modelClass);
            //if (serviceBean instanceof CoreService) {
            //    CoreService<T> service = (CoreService<T>) serviceBean;
            //    service.removeByCompletely(condition);
            //} else {
            //    throw new IllegalLogicException("服务不支持默认【removeByCompletely】方法！单据类型：" + modelClass);
            //}
        } catch (Exception e) {
            log.error("删除失败", e);
            throw new FeignServerException(e.getMessage());
        }
    }

    private <T extends Core> CoreService<T> getServiceBean(String modelClass, String methodName) throws Exception{
        String serviceName = StringUtils.firstAlpha2LowerCase(modelClass.substring(modelClass.lastIndexOf(".") + 1)) + "Service";
        Object serviceBean = SpringUtil.getBean(serviceName);
        if (serviceBean instanceof CoreService) {
            CoreService<T> service = (CoreService<T>) serviceBean;
            return service;
        } else {
            throw new IllegalLogicException("服务不支持默认【" + methodName + "】方法！单据类型：" + modelClass);
        }
    }
}
